package systemerror

import (
	"fmt"
	"goTestToMod/rate_limiter_test/utility/resourceloader"
)

const (
	WicErrorType         string = "wicError"
	UserDefinedErrorType string = "userError"
	ThirdPkgErrorType    string = "thirdPkgError"
	HttpErrorType        string = "httpErrorType"
)

//如果不做处理的异常，比如wic接口调用异常或者第三方包异常，可以用原生的异常，在error统一处理模块会处理，减少改动
type SystemError struct {
	ErrCode      string        //目前预留,用来填充response的的Code码,可不填先
	HttpCode     int           //http code码
	ErrorId      string        //error标识，去配置文件的哪个位置获取信息
	ErrType      string        //异常类型（wic error, system defined error, third pkg error）
	Parameters   []interface{} //存储动态参数,go用的，python可以定义成map
	OriginalErr  error         //存储wic或者第三方包抛出来的异常，抛出给前端使用用户
	ErrDetailMsg string        //特用来解决调用用例库或者wic接口，存储详情信息,用于后端生产环境定位
}

func NewUserDefinedErrorWithoutPara(errorId string) *SystemError {
	return &SystemError{ErrorId: errorId, ErrType: UserDefinedErrorType}
}

func NewUserDefinedError(errorId string, parameters ...interface{}) *SystemError {
	return &SystemError{ErrorId: errorId, ErrType: UserDefinedErrorType, Parameters: parameters}
}

func NewUserDefinedErrorWithCode(errorId string, httpCode int, parameters ...interface{}) *SystemError {
	return &SystemError{ErrorId: errorId, ErrType: UserDefinedErrorType, HttpCode: httpCode, Parameters: parameters}
}

//特意用来存储wic,testlib接口异常,特用于http底层
func NewHttpTypeError(msg string, errDeatilMsg string) *SystemError {
	return &SystemError{OriginalErr: fmt.Errorf("%s", msg), ErrDetailMsg: errDeatilMsg, ErrType: HttpErrorType}
}

func (this *SystemError) Error() string {
	if this.OriginalErr != nil {
		return this.OriginalErr.Error()
	}
	return ""
}

//原生的返回空字符串
func GetErrorId(err error) string {
	systemErr, ok := err.(*SystemError)
	if ok {
		return systemErr.ErrorId
	}
	return ""
}

func GetErrMsg(err error, language string) (string, string, error) {
	langType := resourceloader.GetLanguageType(language)
	systemErr, ok := err.(*SystemError)
	if !ok {
		return err.Error(), "", nil
	} else {
		if systemErr.ErrType == HttpErrorType {
			return systemErr.ErrDetailMsg, systemErr.OriginalErr.Error(), nil
		}
		errValue, exist := resourceloader.GetInstance().GetErrorResource(langType, systemErr.ErrorId)
		if !exist {
			return "", "", fmt.Errorf("errId:%s, the error no find in resource", systemErr.ErrorId)
		}
		return fmt.Sprintf(errValue, systemErr.Parameters...), "", nil
	}
}

func GetErrDetailMsg(err error, language string) (string, error) {
	langType := resourceloader.GetLanguageType(language)
	systemErr, ok := err.(*SystemError)
	if !ok {
		return err.Error(), nil
	} else {
		if systemErr.ErrType == HttpErrorType {
			return systemErr.ErrDetailMsg, nil
		}
		errValue, exist := resourceloader.GetInstance().GetErrorResource(langType, systemErr.ErrorId)
		if !exist {
			return "", fmt.Errorf("errId:%s, the error no find in resource", systemErr.ErrorId)
		}
		return fmt.Sprintf(errValue, systemErr.Parameters...), nil
	}
}
